<!--
 * @description:
 * @author: huangpeng
 * @date: 2023年08月11日 16:11
 * @Copyright:  2022-2023
!-->
<template>
  <div class="article-info-container">
    <div class="article-info-image-main" ref="articleInfoImage">
      <div class="article-info-image" v-if="article.blogImage">
        <img :src="article.blogImage" class="article-img" alt="">
      </div>
      <div class="article-info-remark">
        <!-- 作者 -->
        <!-- <div class="article-author">
          <el-image
              :src="article.user?.avatar || ''"
              :alt="article.user?.userName || ''"
              fit="cover"
              class="user-avatar"
              @click="handleUserCard(article.user.id)"
          />
          <span class="demonstration">{{article.user?.userName || ''}}</span>
        </div>-->
        <div class="article-info-remark-content">
          <span id="article-info-remark-title" class="article-info-remark-title">
          </span>
          <span id="article-info-remark-cursor">_</span>
        </div>
        <div class="article-other">
          <div>
            <span style="color: white"> <svg-icon icon-class="time"/> {{ formatToSubDay(article.createTime) }}前&nbsp;&nbsp;</span>
          </div>
          <div>
            <span style="color: white"><svg-icon icon-class="boolean"/> 勘误</span>
          </div>
          <div>
            <span style="color: white;"><svg-icon icon-class="eye-open"/> {{ article.blogRead }} 阅读</span>
          </div>
        </div>
        <div class="article-other-tag">
          <!-- 标签 -->
          <div v-for="(item, index) in article.tagList" :key="item.tagId" class="tag-item">
            <router-link :to="'/search?activeTab=recommend&activeSearchTypeTab=blog&keyWord=&blogType=&typeName=&blogTag=' + item.tagName" tag="p">
              <el-tag :type="tagType[index]" size="mini">
                <el-icon class="el-icon-discount" /> {{ item.tagName }}
              </el-tag>
            </router-link>
          </div>
        </div>
      </div>
      <div class="article-original">
        <span v-if="article.original == 0">转载</span>
        <span v-else>原创</span>
      </div>
    </div>
    <div class="article-info-main">
      <div class="article-info-left-container">
        <el-card class="article-info-card">
          <div class="article-info">
            <div class="copyright-about">
              <span style="color: #38485a;font-weight: 500;">版权声明：</span>
              <span v-if="article.original == 0">文章转载自：{{ article.blogSource }}, 版权归原作者所有</span>
              <span v-else>本文为{{ siteConfig.siteName }}原创文章，转载无需和我联系，但请注明来自{{ siteConfig.siteName }} {{ siteConfig.siteUrl }}</span>
            </div>
            <div class="article-content" ref="blogContent" v-html="article.blogContent">
              <!-- 内容开始 -->
              <!-- 内容结束 -->
            </div>
            <div class="article-action">
              <div class="article-good">
                <div class="nav-item" @click="handleOptions('LIKE')">
                  <el-tooltip content="点赞" placement="bottom" effect="light">
                    <svg-icon v-if="article.dvLike === 1" icon-class="like2" />
                    <svg-icon v-else icon-class="like" />
                  </el-tooltip>
                </div>
              </div>
              <div class="article-collection" @click="handleOptions('DISLIKE')">
                <div class="nav-item">
                  <el-tooltip content="点踩" placement="bottom" effect="light">
                    <svg-icon v-if="article.dvDislike === 1" icon-class="dislike2" />
                    <svg-icon v-else icon-class="dislike" />
                  </el-tooltip>
                </div>
              </div>
              <div class="article-collection" @click="handleOptions('COLLECTION')">
                <div class="nav-item">
                  <el-tooltip content="收藏" placement="bottom" effect="light">
                    <svg-icon v-if="article.dvCollection === 1" icon-class="star3" />
                    <svg-icon v-else icon-class="star2" />
                  </el-tooltip>
                </div>
              </div>
            </div>
          </div>
          <!-- 推荐文章 -->
          <div class="recommend-info" id="recommend-info">
            <el-divider content-position="left" class="article-info-divider"><el-icon class="el-icon-reading"/> 推荐文章</el-divider>
            <div class="recommend-container">
              <div class="recommend-list" v-if="recommendBlogList.length > 0">
                <div class="recommend-item" v-for="(item, index) in recommendBlogList.slice(0, 5)" :key="index">
                  <router-link :to="'/info/' + item.id" tag="span">
                    {{ item.blogTitle }}
                  </router-link>
                </div>
              </div>
              <div class="recommend-list" v-if="recommendBlogList.length > 5">
                <div class="recommend-item" v-for="(item, index) in recommendBlogList.slice(5, 10)" :key="index">
                  <router-link :to="'/info/' + item.id" tag="span">
                    {{ item.blogTitle }}
                  </router-link>
                </div>
              </div>
            </div>
          </div>
          <!-- 评论信息 -->
          <div class="comment-info" id="comment-info">
            <el-divider content-position="left" class="article-info-divider"><el-icon class="el-icon-chat-square"/>文章评论</el-divider>
            <comment-box
                :article="article"
                :toCommentInfo="toCommentInfo"
                @refreshCommentList="getCommentList"
            />
            <!-- 评论列表 -->
            <comment-list
                v-if="commentList.length > 0"
                :comment-list="commentList"
                :comment-info="commentList[0]"
                :maxReplyLevel="4"
                :article="article"
                @refreshCommentList="getCommentList"
            />
            <div class="no-comment" v-if="commentList.length === 0 && article.commentOpen === '0'">还没有评论，快来抢沙发吧！</div>
          </div>
        </el-card>
        <!-- 左边导航  -->
        <div class="left-navigation">
          <div class="nav-item" @click="handleOptions('LIKE')">
            <el-tooltip content="点赞" placement="left" effect="light">
              <el-badge :value="article.blogGoods" class="item">
                <svg-icon v-if="article.dvLike === 1" icon-class="like2" />
                <svg-icon v-else icon-class="like" />
              </el-badge>
            </el-tooltip>
          </div>
          <div class="nav-item" @click="handleOptions('DISLIKE')">
            <el-tooltip content="点踩" placement="left" effect="light">
              <el-badge :value="article.blogNoGoods" class="item">
                <svg-icon v-if="article.dvDislike === 1" icon-class="dislike2" />
                <svg-icon v-else icon-class="dislike" />
              </el-badge>
            </el-tooltip>
          </div>
          <div class="nav-item" @click="handleOptions('COLLECTION')">
            <el-tooltip content="收藏" placement="left" effect="light">
              <el-badge :value="article.blogCollection" class="item">
                <svg-icon v-if="article.dvCollection === 1" icon-class="star3" />
                <svg-icon v-else icon-class="star2" />
              </el-badge>
            </el-tooltip>
          </div>
          <div class="nav-item">
            <el-tooltip content="评论" placement="left" effect="light">
              <a href="#recommend-info">
                <el-badge :value="article.blogComment" class="item">
                  <svg-icon icon-class="comment" />
                </el-badge>
              </a >
            </el-tooltip>
          </div>
        </div>
        <!-- 评论列表 -->
      </div>
      <div class="article-info-right-container">
        <LoginHint v-if="[null, '', undefined].includes(token)"/>
        <UserStatistics v-if="userIllustrate !== null" :userIllustrate="userIllustrate" @getUserIllustrate="getUserIllustrate" :dvShowIllustrateButton="true"/>
        <Directory :tocDataTree="tocDataTree" @changeScrollHeight="changeScrollHeight"/>
      </div>
    </div>
    <el-image-viewer
        v-if="showViewer"
        :on-close="()=>{showViewer=false}"
        :url-list="viewImgList"
    />
  </div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import CommentBox from '@/components/CommentBox/index.vue';
import CommentList from '@/components/CommentList/index.vue';
import store from "@/store";
import { formatToSubDay } from "@/utils/DateUtil";
import {getArticleInfo, getRecommendBlogByUserId, readBlog} from "@/api/blog/article";
import Prismjs from 'prismjs';
import { listComment } from "@/api/blog/comment";
import { insertOrUpdateBlogOptions } from "@/api/blog/blogOptions";
import Directory from "@/views/article/directory/directory.vue";
import UserStatistics from "@/components/UserStatistics/index.vue";
import LoginHint from '@/components/LoginHint/index.vue';
import { getUserIllustrate } from "@/api/blog/baseUser";
import ElImageViewer from "element-ui/packages/image/src/image-viewer.vue";

@Component({
  components: {
    UserStatistics,
    CommentBox,
    CommentList,
    Directory,
    LoginHint,
    ElImageViewer
  },
  methods: {
    formatToSubDay
  }
})
export default class index extends Vue {

  /** 文章对象数据 */
  private article:any = {};

  /** 当前登录用户信息 */
  get user() {
    return store.getters.userInfo;
  }

  /** 标签颜色 */
  public tagType: any = ['success', 'warning', 'danger', 'info'];

  /** 系统配置信息 */
  get siteConfig() {
    return store.getters.siteConfig;
  }

  /** token */
  get token() {
    return store.getters.token;
  }

  /** 评论列表 */
  public commentList:any = [];

  /** 文章id */
  private articleId = this.$route.params.id;

  /** 评论对象信息 */
  public toCommentInfo: any = {
    commentId: '',
    userId: ''
  }

  /** 目录树数据 */
  private tocDataTree:any = [];

  /** 当前登录用户信息 */
  private userIllustrate:any = null;

  /** 定时任务 */
  private articleTitleTimer: any = null;

  /** 当前用户的推荐文章列表 */
  private recommendBlogList: any = [];

  /** 是否显示图片预览 */
  private showViewer: any = false;

  /** 图片预览列表 */
  private viewImgList: any = [];

  private async created() {
    await this.getArticleInfo();
    await this.makeToc();
    await this.addImgClickEvent();
    await this.getUserIllustrate(this.article.userId);
    this.getRecommendBlog();
    this.getCommentList();
  }

  private mounted() {
    this.$nextTick(() => {
      const el:any = document.getElementById('layout-container');
      el.scrollTop = 0;
      document.addEventListener("scroll", this.handleScroll, true);
    })
  }

  /** 销毁事件监听 */
  private beforeDestroy() {
    document.removeEventListener("scroll", this.handleScroll, true);
    this.removeImgClickEvent();
  }

  /** 获取用户相关信息 */
  private async getUserIllustrate(userId: string) {
    await getUserIllustrate(userId).then((res: any) => {
      this.userIllustrate = res.data;
    })
  }

  /** 获取评论列表 */
  private getCommentList() {
    listComment({toBlogId: this.articleId}).then((res: any) => {
      this.commentList = res.data;
    })
  }

  /** 获取文章信息 */
  private async getArticleInfo(dvNoneOpt:  boolean = true) {
    await getArticleInfo(this.articleId).then((res: any) => {
      this.article = res.data;
      if (dvNoneOpt) {
        this.handleArticleTitle(res.data.blogTitle);
        readBlog(this.articleId).then(()=>{});
        if (this.user.id) {
          // 更新用户阅读记录
          this.handleOptions('READ');
        }
      }
      this.$nextTick(() => {
        Prismjs.highlightAll();
      })
    })
  }

  /** 文章标题一个一个的显示出来 */
  private handleArticleTitle(text: string) {
    let i = 0;
    const num = text.length;
    const el: any = document.getElementById('article-info-remark-title');
    clearInterval(this.articleTitleTimer);
    if (el !== null) {
      el.innerText = '';
      this.articleTitleTimer = setInterval(() => {
        const shower = text.substr(0, i);
        const el: any = document.getElementById('article-info-remark-title');
        el.innerText = shower;
        if(i >= num){
          clearInterval(this.articleTitleTimer);
        } else {
          i++;
        }
      }, 150);
    }
  }

  /** 点赞 */
  private handleOptions(type: string) {
    const data = {
      businessType: type,
      blogId: this.articleId
    }
    insertOrUpdateBlogOptions(data).then((res: any) => {
      if (type !== "READ") {
        this.$modal.msgSuccess(res.msg);
        this.getArticleInfo(false);
      }
    })
  }

  /** 给文章详情的图片添加点击事件 */
  private async addImgClickEvent() {
    const contentRef: any = this.$refs.blogContent;
    const imgDos = contentRef.querySelectorAll('img');
    imgDos.forEach((item: any) => {
      item.addEventListener('click', this.handleShowViewer)
    })
  }

  /** 给文章详情的图片移除点击事件 */
  private async removeImgClickEvent() {
    const contentRef: any = this.$refs.blogContent;
    const imgDos = contentRef.querySelectorAll('img');
    imgDos.forEach((item: any) => {
      item.removeEventListener('click', this.handleShowViewer)
    })
  }

  /** 展示图片预览 */
  private handleShowViewer($event: any) {
    this.viewImgList = [$event.target.src];
    this.showViewer = true;
  }

  /** 生成目录 */
  private async makeToc(){
    const tocTags = ["H1","H2","H3","H4","H5","H6"];
    const tocArr: any = [];
    const contentRef: any = this.$refs.blogContent;
    const headDos = Array.from(contentRef.childNodes).filter((item: any) => tocTags.includes(item.tagName));
    headDos.forEach((item: any, index: any, arr: any) => {
      item.id = `h-${index + 1}`;
      let previous = arr.filter((i: any, j: any) => j < index);
      previous = previous.filter(
          (i: any) => tocTags.filter(
              (i,j) => j <= tocTags.findIndex(i => i == item.tagName)
          ).includes(i.tagName)
      );
      previous = previous.sort((a: any, b: any) => -(a.id.replace('h-','')) - b.id.replace('h-',''));
      const prev = previous.find((i: any) => i.tagName != item.tagName);
      // this.maxum = Math.max(this.maxum, index + 1)
      tocArr.push({
        id:index + 1,
        tag:item.tagName,
        label:item.innerText,
        p_id:item.tagName == "H1" || prev == null ? 0 : Number(prev.id.replace("h-",'')),// 抛出父级id
        children: []
      })
    })
    this.tocDataTree = this.toTree(tocArr);
  }

  /** 生成树结构 */
  private toTree(data: any){
    data.forEach(function (item: any) {
      item.children = [];
    });
    const map: any = {};
    data.forEach(function (item: any) {
      map[item.id] = item;
    });
    const val: any = [];
    data.forEach(function (item: any) {
      const parent = map[item.p_id];
      if (parent) {
        (parent.children || (parent.children = [])).push(item);
      } else {
        val.push(item);
      }
    });
    return val;
  }

  /** 改变滚动条位置 */
  private changeScrollHeight(record: any){
    const el:any = document.getElementById('layout-container');
    // el-scrollbar获取页面当前位置的属性，定位也是通过改变这个
    let cur = el.scrollTop
    let flag = false
    let step = 20
    // 由于有可能是向上滑，有可能向下滑，所以需要考虑移动的正负
    if (record < cur) {
      step = -step;
      flag = true
    }else if (record == cur) {
      return
    }
    // 设置动画，具体含义就是按照每8毫秒执行一次向上移动指定的步长，这样就是一个动画
    const timer = setInterval(() => {
      if (flag) {
        //  说明小于0
        if (cur + step < record) {
          // 说明移动多了，这时候我们改变移动距离，直接移动到指定位置即可
          el.scrollTop = record;
          clearInterval(timer);
        } else {
          el.scrollTop = cur + step;
        }
      } else {
        if (cur + step > record) {
          // 说明移动多了，这时候我们改变移动距离，直接移动到指定位置即可
          el.scrollTop = record;
          clearInterval(timer);
        } else {
          el.scrollTop = cur + step;
        }
      }
      cur += step;
    }, 3);
  }

  /** 编写滚动条事件 */
  handleScroll() {
    // 获取滚动条元素对象
    let el = document.getElementById('layout-container');
    if (el !== null) {
      // 获取需要固定的元素对象
      const rightElArr = document.getElementsByClassName('article-info-right-container');
      const leftNavigationElArr = document.getElementsByClassName('left-navigation');
      if (rightElArr.length > 0) {
        let rightEl = rightElArr[0];
        // 判断滚动条的高度（大于380，给固定元素添加 class）
        if (el.scrollTop > 424) {
          rightEl.classList.add('article-info-right-container-fixed');
        } else {
          rightEl.classList.remove('article-info-right-container-fixed')
        }
      }
      if (leftNavigationElArr.length > 0) {
        let leftNavigationEl = leftNavigationElArr[0];
        if (el.scrollTop > 424) {
          leftNavigationEl.classList.add('left-navigation-fixed');
        } else {
          leftNavigationEl.classList.remove('left-navigation-fixed');
        }
      }
    }
  }

  /** 点击用户列表用户卡片 */
  public handleUserCard(userId: any) {
    this.$router.push({path: '/userCenter?userId=' + userId});
  }

  /** 获取用户的推荐文章列表 */
  private getRecommendBlog() {
    if (this.user.id) {
      getRecommendBlogByUserId(this.user.id).then((res: any) => {
        this.recommendBlogList = res.data;
      })
    }
  }
}
</script>
<style scoped lang="scss">
.article-info-container {
  display: flex;
  flex-direction: column;
  .article-info-image-main {
    height: 450px;
    width: calc(100% + 120px);
    margin-left: -60px;
    border-radius: 10px;
    border: 1px solid #e6ebf5;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
    transition: 0.3s;
    overflow: hidden;
    position: relative;
    .article-info-image {
      height: 100%;
      width: 100%;
      .article-img {
        width: 100%;
        height: 100%;
        object-fit: cover; /* 使图片保持高宽比并填充整个容器 */
        transition: all 0.6s;
      }
    }
    .article-info-remark {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      .tag-item{
        margin-right: 10px;
      }
      .article-author {
        height: 45px;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        .user-avatar {
          width: 45px;
          height: 45px;
          border-radius: 50%;
          box-shadow: 2px 2px 6px rgba(0,0,0, .12);
          background-color: #ffffff;
          border: 2px solid gold;
          cursor: pointer;
        }
        .demonstration {
          margin: 0 15px 0 5px;
          color: #e8ca2d;
        }
      }
      .article-other {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        padding: 5px;
        background-color: rgba(0, 0, 0, 0.3);
      }
      .article-other span {
        margin-right: 15px;
      }
      .article-other-tag {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
      }
      .article-info-remark-content {
        margin-left: 20px;
        margin-right: 20px;
        text-align: center;
        padding: 10px;
        background-color: rgba(0, 0, 0, 0.3);
        .article-info-remark-title {
          text-align: center;
          font-size: 25px;
          font-weight: bold;
          color: #ffffff;
        }
        #article-info-remark-cursor {
          font-size: 25px;
          font-weight: bold;
          color: white;
          animation: cursor-blink-animation 1s linear infinite;
        }
        @keyframes cursor-blink-animation {
          0% { opacity: 1; }
          50% { opacity: 0; }
          100% { opacity: 1; }
        }
      }
    }
    .article-original{
      position: absolute;
      top: 0;
      padding-left: 10px;
      padding-right: 80px;
      padding-bottom: 70px;
      text-align: center;
      line-height: 40px;
      color: white;
      font-size: 15px;
      background-image: linear-gradient(142deg, rgb(114, 171, 255) 31%, transparent 0);
    }
  }
  .article-info-image-main:hover {
    transform: translateY(-5px);
    transition: all .6s ease;
    box-shadow: 5px 10px 6px rgba(165, 165, 165, 0.7);
  }
  .article-info-main {
    margin-top: -20px;
    display: flex;
    flex-direction: row;
    position: relative;
    .article-info-left-container {
      width: calc(71% - 10px);
      .article-info-card {
        background-image: linear-gradient(90deg,rgba(50,0,0,.05) 3%,transparent 0),
        linear-gradient(1turn,rgba(50,0,0,.05) 3%,transparent 0);
        background-size: 20px 20px;
        background-position: 50%;
        position: relative;
        padding-bottom: 145px;
        .article-info {
          padding: 10px 5px;
          min-height: 800px;
        }
        .copyright-about{
          color: #888;
          background-color: #ecf8ff;
          line-height: 20px;
          padding-top: 5px;
          padding-bottom: 5px;
          padding-left: 10px;
          margin-bottom: 5px;
          font-size: 13px;
          border-left: 5px solid #50bfff;
        }
        .article-content{
          font-size: 17px;
          color: var(--text);
          min-height: 500px;
          ::v-deep img {
            max-width: 100% !important;
            height: auto !important;
          }
        }
        .article-action {
          width: 300px;
          display: flex;
          flex-direction: row;
          justify-content: space-evenly;
          font-size: 24px;
          margin: 20px auto auto;
          .article-action-active{
            /* 标识当前是否已点赞，是否已收藏 */
            color: red !important;
          }
          .article-good{
            color: #676767;
          }
          .article-good:hover{
            color: #5f9fff;
          }
          .article-collection{
            color: #676767;
          }
          .article-collection:hover{
            color: #5f9fff;
          }
        }
        .article-info-divider {
          background-color: #c2c2c2;
          height: 2px;
          ::v-deep .el-divider__text {
            font-size: 16px;
            font-weight: 500;
          }
        }
      }
      .recommend-info {
        .recommend-container {
          display: flex;
          flex-direction: row;
          justify-content: space-between;
          align-items: flex-start;
          margin: 0 30px;
          .recommend-list {
            display: flex;
            flex-direction: column;
            justify-content: start;
            align-items: start;
            width: calc(50% - 15px);
            overflow: hidden;
            .recommend-item {
              width: 100%;
              font-size: 16px;
              line-height: 40px;
              cursor: pointer;
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
            }
          }
        }
      }
      .comment-info {
        .no-comment {
          text-align: center;
        }
      }
      .left-navigation {
        position: absolute;
        top: 20px;
        left: -54px;
        display: flex;
        flex-direction: column;
      }
      .left-navigation-fixed {
        position: fixed;
        top: 90px;
        left: calc((100% - 1300px)/2 - 40px);
      }
    }
    .article-info-right-container {
      width: calc(29% - 10px);
      margin-left: 20px;
      min-height: 200px;
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      gap: 20px;
    }
    .article-info-right-container-fixed{
      top: 80px;
      z-index: 2000;
      position: fixed;
      width: 355.39px;
      right: calc((100% - 1300px) / 2 + 24px);
    }
  }
}

@media only screen and (max-width: 1400px){
  .article-info-container {
    .article-info-image-main {
      width: 100% !important;
      margin-left: 0 !important;
    }
    .article-info-main {
      margin-top: 10px !important;
      flex-direction: column;
    }
    .article-info-left-container {
      width: 100% !important;
    }
    .article-info-right-container {
      width: 100% !important;
      margin-left: 0 !important;
      margin-top: 20px;
      position: relative !important;
      right: unset !important;
      top: unset !important;
    }
    .left-navigation {
      display: none !important;
    }
  }
}
@media only screen and (max-width: 850px) {
  .article-tag {
    display: flex !important;
  }
  .content-count {
    display: none !important;
  }
  ::v-deep .article-content {
    img{
      max-width: 100% !important;
    }
    code, pre {
      font-size: 0.8em !important;
    }
  }
}
@media only screen and (min-width: 555px) and (max-width: 850px) {
  .article-info {
    padding: 0 !important;
  }
}
@media only screen and (max-width: 555px) {
  .article-info {
    padding: 0 !important;
  }
  .article-info-remark-title {
    font-size: 16px !important;
    font-weight: 550 !important;
  }
  .recommend-container {
    flex-direction: column !important;
  }
  .recommend-list {
    width: 100% !important;
  }
}
@media only screen and (max-width: 550px) {
  .article-info-image-main {
    height: 320px !important;
  }
}
</style>
